package com.sdy.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.DurationFormatUtils;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Created by zzq on 2017/8/28.
 */
@Slf4j
public class DateUtil {
    private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
    private static final Object object = new Object();

    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static final String DATE_FORMAT_YYYYMMDD = "yyyyMMdd";

    public DateUtil() {
    }

    public static String formatDate(Date date) {
        return getDate(date, "yyyy-MM-dd");
    }

    public static String formatTime(Date date) {
        return getDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    public static String getDate(Date date, String parttern) {
        return dateToString(date, parttern);
    }

    public static String getDate(String pattern) {
        return getDate(new Date(), pattern);
    }

    public static String dateToString(Date date, String pattern) {
        String dateString = null;
        if (date != null) {
            try {
                dateString = getDateFormat(pattern).format(date);
            } catch (Exception var4) {
                ;
            }
        }

        return dateString;
    }

    public static String getCurrentTimeStamp() {
        return getDate(new Date(), "yyyyMMddHHmmss.SSS");
    }

    private static SimpleDateFormat getDateFormat(String pattern) throws RuntimeException {
        if (StringUtils.isBlank(pattern)) {
            pattern = DATETIME_FORMAT;
        }

        SimpleDateFormat dateFormat = (SimpleDateFormat) threadLocal.get();
        if (dateFormat == null) {
            synchronized (object) {
                dateFormat = new SimpleDateFormat(pattern);
                dateFormat.setLenient(false);
                threadLocal.set(dateFormat);
            }
        }

        dateFormat.applyPattern(pattern);
        return dateFormat;
    }


    /**
     * 把传入的日期字符串，转换成指定格式的日期对象
     *
     * @param dateString 日期字符串
     * @param pattern    指定转换格式
     * @return Date  日期对象
     */
    public static Date getDate(String dateString, String pattern) {
        SimpleDateFormat df = null;
        Date date = null;
        if (dateString != null) {
            try {
                df = new SimpleDateFormat(pattern);
                date = df.parse(dateString);
            } catch (Exception e) {
                log.error("日期格式转换失败, dateString={}, pattern={}", dateString, pattern, e);
            }
        }
        return date;
    }


    /**
     * 日期相加
     *
     * @param date 日期
     * @param day  天数，可为负数
     * @return 返回相加后的日期
     */
    public static Date addDate(Date date, int day) {
        java.util.Calendar c = java.util.Calendar.getInstance();
        c.setTimeInMillis(getMillis(date) + ((long) day) * 24 * 3600 * 1000);
        return c.getTime();
    }

    /**
     * 增加秒
     *
     * @param date   日期
     * @param second 秒数，可为负数
     * @return 返回相加后的日期
     */
    public static Date addSecond(Date date, int second) {
        java.util.Calendar c = java.util.Calendar.getInstance();
        c.setTimeInMillis(getMillis(date) + ((long) second) * 1000);
        return c.getTime();
    }

    /**
     * 获取日期开始时间
     *
     * @param date 日期
     * @return 返回相加后的日期
     */
    public static Date getDateBegin(Date date) {
        return getDate(getDate(date, "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 获取日期结束时间
     *
     * @param date 日期
     * @return 返回相加后的日期
     */
    public static Date getDateEnd(Date date) {
        return getDate(getDate(date, "yyyy-MM-dd") + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
    }

    public static Date getWeekEnd(Date date) {
        int week = dateToWeek(date);
        week = week == 0 ? 7 : week;
        return getDateEnd(addDate(date, 7 - week));
    }

    public static Date getMonthBegin(Date date) {
        return getDateBegin(DateUtils.setDays(date, 1));
    }

    public static Date getMonthEnd(Date date) {
        return addSecond(getDateBegin(DateUtils.setDays(DateUtils.addMonths(date, 1), 1)), -1);
    }

    public static Date addMonth(Date date, int month) {
        return DateUtils.addMonths(date, month);
    }

    /**
     * 返回毫秒
     *
     * @param date 日期
     * @return 返回毫秒
     */
    public static long getMillis(Date date) {
        java.util.Calendar c = java.util.Calendar.getInstance();
        c.setTime(date);
        return c.getTimeInMillis();
    }

    public static Integer compareDay(Date startDate, Date endDate) {
        return Integer.valueOf(formatPeriod(startDate, endDate, "d"));
    }

    public static String formatPeriod(Date startDate, Date endDate, String format) {
        return formatPeriod(startDate.getTime(), endDate.getTime(), format);
    }

    public static String formatPeriod(long startMillis, long endMillis, String format) {
        return DurationFormatUtils.formatDuration(endMillis - startMillis, format);
    }

    public static int compareYear(Date startDate, Date endDate) {
        return compareDay(startDate, endDate).intValue() / 365;
    }

    public static int diffDay(Date dateBegin, Date dateEnd) {
        Date date1 = DateUtil.getDate(DateUtil.getDate(dateBegin, "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
        Date date2 = DateUtil.getDate(DateUtil.getDate(dateEnd, "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
        return (int) ((date2.getTime() - date1.getTime()) / 86400000);
    }

    /**
     * 根据日期获取 星期 （2019-05-06 ——> 星期一）
     * @param datetime
     * @return
     */
    public static int dateToWeek(Date datetime) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(datetime);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) {
            w = 0;
        }
        return w;
    }

    public static int dateToMonth(Date datetime) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(datetime);
        return cal.get(Calendar.MONTH) + 1;
    }

    public static int dateToDay(Date datetime) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(datetime);
        return cal.get(Calendar.DATE);
    }

    public static void main(String[] args) {
        System.out.println(getMonthBegin(getDate("2020-03-29 01:00:00", DATETIME_FORMAT)));
    }
}
